package org.hentai.bt.scan.table;

import org.hentai.bt.scan.Scan;
import org.hentai.bt.scan.paramter.ScanParameter;

import java.io.File;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;

/**
 * 实现对用户的包扫描
 */
public class ClassScan implements Scan {

    private ScanParameter parameter;

    // 属性 来自属性类
    private String classPath;
    private String packageName;

    public ClassScan(ScanParameter parameter) {
        this.parameter = parameter;
        classPath = parameter.getClassPath();
        packageName = parameter.getPackageName();
    }

    public ClassScan(String classPath, String packageName) {
        this.classPath = classPath;
        this.packageName = packageName;
    }

    public void setParameter(ScanParameter parameter) {
        this.parameter = parameter;
        classPath = parameter.getClassPath();
        packageName = parameter.getPackageName();
    }

    public void setClassPath(String classPath) {
        this.classPath = classPath;
    }

    public void setPackageName(String packageName) {
        this.packageName = packageName;
    }

    @Override
    public Set<Class<?>> search(Predicate<Class<?>> predicate) {
        String classPath = this.classPath;

        String basePackPath = packageName.replace(".", File.separator); // 包路径换位class路径
        String searchPath = String.format("%s%s", classPath, basePackPath);
        return new ClassSearcher().doPath(new File(searchPath), packageName, predicate, true);
    }

    private static class ClassSearcher {
        private Set<Class<?>> classPaths = new HashSet<>();

        private Set<Class<?>> doPath(File file, String packageName, Predicate<Class<?>> predicate, boolean flag) {
            String fileName = file.getName();

            // 文件夹
            if (file.isDirectory()) {
                File[] files = file.listFiles();
                if (!flag) {
                    packageName = String.format("%s.%s", packageName, fileName);
                }

                for (File fc : files) {
                    doPath(fc, packageName, predicate, false);
                }
            } else { // 文件
                // 判断是不是.class
                if (fileName.endsWith(CLASS_SUFFIX)) {
                    // 是则加入集合
                    try {
                        Class<?> clazz = Class.forName(
                                String.format("%s.%s", packageName, fileName.substring(0, fileName.lastIndexOf(".")))
                        );
                        if (predicate==null || predicate.test(clazz)) {
                            classPaths.add(clazz);
                        }
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                }
            }

            return classPaths;
        }
    }
}
